package com.ruibang.glass.equipment.service.impl.device;

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.common.constants.Constants;
import com.ruibang.glass.common.constants.RedisKey;
import com.ruibang.glass.common.domain.GlobalUser;
import com.ruibang.glass.common.domain.camunda.BpmProcessInstanceCreate;
import com.ruibang.glass.common.domain.camunda.BpmProcessInstanceStatus;
import com.ruibang.glass.common.domain.file.FileBusiness;
import com.ruibang.glass.equipment.domain.req.DeviceStaticsReq;
import com.ruibang.glass.equipment.domain.req.device.HazardAccountReq;
import com.ruibang.glass.equipment.dto.HazardAllStaticsDTO;
import com.ruibang.glass.equipment.dto.HazardLineStaticsDTO;
import com.ruibang.glass.equipment.dto.HazardStaticsDTO;
import com.ruibang.glass.equipment.entity.device.HazardAccount;
import com.ruibang.glass.equipment.feign.CamundaApi;
import com.ruibang.glass.equipment.feign.FileApi;
import com.ruibang.glass.equipment.mapper.device.HazardAccountMapper;
import com.ruibang.glass.equipment.service.CommonService;
import com.ruibang.glass.equipment.service.HazardAccountService;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.common.constant.CommonConstant;
import com.teaming.cloud.framework2.common.model.ResultBody;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 隐患台账列表服务类
 * </p>
 *
 * @author mameng
 * @since 2024-03-20
 */
@Slf4j
@Service
public class HazardAccountServiceImpl extends ServiceImpl<HazardAccountMapper, HazardAccount> implements HazardAccountService {

    @Autowired
    private FileApi fileApi;

    @Autowired
    private CommonService commonService;

    @Autowired
    private CamundaApi camundaApi;

    @Autowired
    private RedisSingleService redisService;


    /**
     * 隐患台账列表
     *
     * @param accountReq
     * @return
     */
    @Override
    public IPage<HazardAccount> queryPage(HazardAccountReq accountReq) {
        IPage<HazardAccount> page = baseMapper.queryHazardAccount(new Page<>(accountReq.getPageNo(), accountReq.getPageSize()), accountReq);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return page;
        }
        List<String> businessKeys = page.getRecords().stream().map(HazardAccount::getHazardId).collect(Collectors.toList());
        Map<String, BpmProcessInstanceStatus> processInstanceMap = null;
        Map<Object, Object> userMap = redisService.hmget(RedisKey.USER_GROUP_TYPE);
        //获取业务流程状态
        ResultBody<List<BpmProcessInstanceStatus>> resultBody = camundaApi.queryProcessInstanceStatus(businessKeys);
        if (resultBody != null && CollectionUtils.isNotEmpty(resultBody.getData())) {
            processInstanceMap = resultBody.getData().stream().collect(Collectors.toMap(BpmProcessInstanceStatus::getBusinessKey, bp -> bp, (s1, s2) -> s1));
        }
        for (HazardAccount hazardAccount : page.getRecords()) {
            if (processInstanceMap != null) {
                BpmProcessInstanceStatus pim = processInstanceMap.get(hazardAccount.getHazardId());
                if (pim != null) {
                    hazardAccount.setProcessId(pim.getProcessInstanceId());
                    hazardAccount.setNodeName(pim.getNodeName());
                    if ("Activity_066rkwb".equals(pim.getNodeKey())) {
                        hazardAccount.setHazardStatus(CommonConstant.ONE_STR);
                    } else if ("Activity_0sisuwd".equals(pim.getNodeKey())) {
                        hazardAccount.setHazardStatus(CommonConstant.TWO_STR);
                    } else if ("Activity_14czapn".equals(pim.getNodeKey())) {
                        hazardAccount.setHazardStatus(CommonConstant.THREE_STR);
                    } else {
                        hazardAccount.setHazardStatus(CommonConstant.THREE_STR);
                    }
                    hazardAccount.setCurrentUser(pim.getUserId());
                } else {
                    hazardAccount.setHazardStatus(CommonConstant.THREE_STR);
                }
            }

            if (StringUtils.isNotBlank(hazardAccount.getHazardType())) {
                hazardAccount.setHazardStatus(hazardAccount.getHazardType());
            }


            if (userMap != null) {
                hazardAccount.setRectifierName(userMap.get(hazardAccount.getRectifierId()) == null
                        ? "" : userMap.get(hazardAccount.getRectifierId()).toString());
                hazardAccount.setReporterName(userMap.get(hazardAccount.getReporterId()) == null
                        ? "" : userMap.get(hazardAccount.getReporterId()).toString());
            }
        }
        return page;
    }

    /**
     * 跟新删除
     *
     * @param point
     * @return
     */
    @Override
    public ResultBody addOrUpdateCheck(HazardAccount point) {

        if (StringUtils.isBlank(point.getHazardId())) {
            GlobalUser user = commonService.getUser();
            if (user != null) {
                point.setReporterId(user.getUserId());
            }
            point.setReportTime(LocalDateTime.now());
            //更新
            baseMapper.insert(point);

            if (CollectionUtils.isNotEmpty(point.getFileIds())) {
                FileBusiness fileBusiness = new FileBusiness();
                fileBusiness.setFileIds(point.getFileIds());
                fileBusiness.setBusinessId(point.getHazardId());
                fileApi.updateBusinessById(fileBusiness);
            }

            BpmProcessInstanceCreate instanceCreate = new BpmProcessInstanceCreate();
            instanceCreate.setBusinessKey(point.getHazardId());
            instanceCreate.setMenuId(point.getMenuId());

            //发起流程
            Map<String, Object> variables = new HashMap<>();
            variables.put(com.ruibang.glass.common.constants.Constants.PROCESS_INSTANCE_STARTER_USER_ID, point.getReporterId());
            variables.put(com.ruibang.glass.common.constants.Constants.PROCESS_INSTANCE_BUSINESS_KEY, point.getHazardId());
            variables.put(com.ruibang.glass.common.constants.Constants.PROCESS_INSTANCE_MENU_ID, point.getMenuId());
            instanceCreate.setVariables(variables);
            commonService.startProcess(instanceCreate);
            return ResultBody.success();
        }

        if (CollectionUtils.isNotEmpty(point.getRemoveIdList())) {
            fileApi.deleteByFileIds(point.getRemoveIdList());
        }

        if (CollectionUtils.isNotEmpty(point.getFileIds())) {
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(point.getFileIds());
            fileBusiness.setBusinessId(point.getHazardId());
            fileApi.updateBusinessById(fileBusiness);
        }


        baseMapper.updateById(point);
        return ResultBody.success();
    }

    @Override
    public ResultBody deviceStatics(DeviceStaticsReq deviceStaticsReq) {
        // 获取所有Id
        List<HazardAccount> hazardAccounts = baseMapper.selectList(Wrappers.<HazardAccount>lambdaQuery().select(HazardAccount::getHazardId));
        List<String> collect = hazardAccounts.stream().map(HazardAccount::getHazardId).collect(Collectors.toList());
        //获取业务流程状态
        ResultBody<List<BpmProcessInstanceStatus>> resultBody = camundaApi.queryProcessInstanceStatus(collect);
        Map<String, BpmProcessInstanceStatus> processInstanceMap = null;
        if (resultBody != null && CollectionUtils.isNotEmpty(resultBody.getData())) {
            processInstanceMap = resultBody.getData().stream().collect(Collectors.toMap(BpmProcessInstanceStatus::getBusinessKey, bp -> bp, (s1, s2) -> s1));
        }
        HazardAllStaticsDTO hazardAllStaticsDTO = new HazardAllStaticsDTO();
        //所有Id
        List<String> allIds = new ArrayList<>();
        //闭环Id
        List<String> bhIds = new ArrayList<>();
        //待指派Id
        List<String> dzpIds = new ArrayList<>();
        //待指待处理Id
        List<String> dclIds = new ArrayList<>();
        if (processInstanceMap != null) {
            for (String id : collect) {
                allIds.add(id);
                if (processInstanceMap.get(id) != null) {
                    if (processInstanceMap.get(id).getResult().equals(Constants.TWO_STR)) {
                        bhIds.add(id);
                    }
                    if (processInstanceMap.get(id).getNodeName().contains("小组")) {
                        dzpIds.add(id);
                    }
                    if (processInstanceMap.get(id).getNodeName().contains("维修")) {
                        dclIds.add(id);
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(allIds)) {
            List<HazardLineStaticsDTO> hazardLineStaticsDTOList = baseMapper.getHazardLineStaticsDTO(deviceStaticsReq, allIds);
            //
            List<HazardLineStaticsDTO> hazardLineBHStaticsDTOList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(bhIds)) {
                hazardLineBHStaticsDTOList = baseMapper.getHazardLineStaticsDTO(deviceStaticsReq, bhIds);
            }
            List<HazardLineStaticsDTO> hazardLineDZPStaticsDTO = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(dzpIds)) {
                hazardLineDZPStaticsDTO = baseMapper.getHazardLineStaticsDTO(deviceStaticsReq, dzpIds);
            }
            List<HazardLineStaticsDTO> hazardLineDCLPStaticsDTO = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(dclIds)) {
                hazardLineDCLPStaticsDTO = baseMapper.getHazardLineStaticsDTO(deviceStaticsReq, dclIds);
            }
            for (HazardLineStaticsDTO hazardLineStaticsDTO : hazardLineStaticsDTOList) {

                for (HazardLineStaticsDTO hazardLineStaticsDTO1 : hazardLineBHStaticsDTOList) {
                    if (StringUtils.equals(hazardLineStaticsDTO.getDeviceName(), hazardLineStaticsDTO1.getDeviceName())) {
                        hazardLineStaticsDTO.setYbhCount(hazardLineStaticsDTO1.getCount());
                    }
                }

                for (HazardLineStaticsDTO hazardLineStaticsDTO1 : hazardLineDZPStaticsDTO) {
                    if (StringUtils.equals(hazardLineStaticsDTO.getDeviceName(), hazardLineStaticsDTO1.getDeviceName())) {
                        hazardLineStaticsDTO.setDzpCount(hazardLineStaticsDTO1.getCount());
                    }
                }
                for (HazardLineStaticsDTO hazardLineStaticsDTO1 : hazardLineDCLPStaticsDTO) {
                    if (StringUtils.equals(hazardLineStaticsDTO.getDeviceName(), hazardLineStaticsDTO1.getDeviceName())) {
                        hazardLineStaticsDTO.setDclCount(hazardLineStaticsDTO1.getCount());
                    }
                }
                if (hazardLineStaticsDTO.getYbhCount() == null) {
                    hazardLineStaticsDTO.setYbhCount(0);
                }
                if (hazardLineStaticsDTO.getDclCount() == null) {
                    hazardLineStaticsDTO.setDclCount(0);
                }
                if (hazardLineStaticsDTO.getDzpCount() == null) {
                    hazardLineStaticsDTO.setDzpCount(0);
                }
            }
            List<String> collect1 = hazardLineStaticsDTOList.stream().map(HazardLineStaticsDTO::getDeviceName).collect(Collectors.toList());
            hazardAllStaticsDTO.setDeviceNameList(collect1);
            List<Integer> collect2 = hazardLineStaticsDTOList.stream().map(HazardLineStaticsDTO::getCount).collect(Collectors.toList());
            hazardAllStaticsDTO.setAllCountList(collect2);
            List<Integer> collect3 = hazardLineStaticsDTOList.stream().map(HazardLineStaticsDTO::getDclCount).collect(Collectors.toList());
            hazardAllStaticsDTO.setDclCountList(collect3);
            List<Integer> collect4 = hazardLineStaticsDTOList.stream().map(HazardLineStaticsDTO::getDzpCount).collect(Collectors.toList());
            hazardAllStaticsDTO.setDzpCountList(collect4);
            List<Integer> collect5 = hazardLineStaticsDTOList.stream().map(HazardLineStaticsDTO::getYbhCount).collect(Collectors.toList());
            hazardAllStaticsDTO.setYbhCountList(collect5);
//            hazardAllStaticsDTO.setHazardLineStaticsDTOList(hazardLineStaticsDTOList);
        }
        List<HazardStaticsDTO> hazardStaticsDTOList = baseMapper.getHazardStaticsDTO(deviceStaticsReq);
//        for (HazardStaticsDTO hazardStaticsDTO : hazardStaticsDTOList) {
//            if (hazardStaticsDTO.getCount() == null) {
//                hazardStaticsDTO.setCount(0);
//            }
//        }

        Map<String, List<HazardStaticsDTO>> collect1 = hazardStaticsDTOList.stream().collect(Collectors.groupingBy(HazardStaticsDTO::getDeviceName));

        List<String> deviceNameList = hazardStaticsDTOList.stream().map(HazardStaticsDTO::getDeviceName).collect(Collectors.toList());
        List<Integer> oneList = new ArrayList<>();
        List<Integer> secondList = new ArrayList<>();
        List<Integer> thirdList = new ArrayList<>();
        for (String deviceNewName : collect1.keySet()) {
            for (String deviceName : deviceNameList) {
                if (deviceNewName.equals(deviceName)) {
                    if (collect1.get(deviceNewName).size() == 3) {
                        for (HazardStaticsDTO hazardStaticsDTO : collect1.get(deviceNewName)) {
                            if (hazardStaticsDTO.getLevelName().contains(Constants.ONE_STR)) {
                                oneList.add(hazardStaticsDTO.getCount());
                            }
                            if (hazardStaticsDTO.getLevelName().contains(Constants.TWO_STR)) {
                                secondList.add(hazardStaticsDTO.getCount());
                            }
                            if (hazardStaticsDTO.getLevelName().equals(Constants.THREE_STR)) {
                                thirdList.add(hazardStaticsDTO.getCount());
                            }
                        }
                    } else {
                        Map<String, List<HazardStaticsDTO>> collect2 = collect1.get(deviceNewName).stream().collect(Collectors.groupingBy(HazardStaticsDTO::getLevelName));
                        if (collect2.get(Constants.ONE_STR) == null) {
                            oneList.add(Constants.ZERO_INT);
                        }else {
                            oneList.add(collect2.get(Constants.ONE_STR).get(0).getCount());
                        }
                        if (collect2.get(Constants.TWO_STR) == null) {
                            secondList.add(Constants.ZERO_INT);
                        }else {
                            secondList.add(collect2.get(Constants.TWO_STR).get(0).getCount());
                        }
                        if (collect2.get(Constants.THREE_STR) == null) {
                            thirdList.add(Constants.ZERO_INT);
                        }else {
                            thirdList.add(collect2.get(Constants.THREE_STR).get(0).getCount());
                        }

                    }
                }

            }
        }
        HazardStaticsDTO hazardStaticsDTO = new HazardStaticsDTO();
        hazardStaticsDTO.setDeviceNameList(deviceNameList);
        hazardStaticsDTO.setTwoList(secondList);
        hazardStaticsDTO.setOneList(oneList);
        hazardStaticsDTO.setThreeList(thirdList);
        hazardAllStaticsDTO.setHazardStaticsDTO(hazardStaticsDTO);
        return ResultBody.success(hazardAllStaticsDTO);
    }

    /**
     * 导出
     *
     * @param accountReq
     * @param response
     */
    @Override
    public void export(HazardAccountReq accountReq, HttpServletResponse response) {
        String fileName = "隐患台账" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss") + ".xlsx";
        try {
            // 对文件名进行URL编码
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");

            // 设置响应内容类型和字符编码
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("UTF-8");

            // 设置Content-Disposition头部，告诉浏览器这是一个文件下载请求
            response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);

            // 获取导出数据
            IPage<HazardAccount> checkList = baseMapper.queryHazardAccount(new Page<HazardAccount>(0L, 2000L), accountReq);
            List<HazardAccount> list = checkList.getRecords();
            Map<Object, Object> userMap = redisService.hmget(RedisKey.USER_GROUP_TYPE);
            if (CollectionUtils.isNotEmpty(list)) {
                for (HazardAccount hazardAccount : list) {
                    if (userMap != null) {
                        hazardAccount.setRectifierName(userMap.get(hazardAccount.getRectifierId()) == null
                                ? "" : userMap.get(hazardAccount.getRectifierId()).toString());
                        hazardAccount.setReporterName(userMap.get(hazardAccount.getReporterId()) == null
                                ? "" : userMap.get(hazardAccount.getReporterId()).toString());
                    }


                }
            }

            // 使用EasyExcel写入数据到响应输出流
            EasyExcel.write(response.getOutputStream(), HazardAccount.class).excelType(ExcelTypeEnum.XLSX).sheet("隐患台账").doWrite(list);

            // 刷新输出流
            response.flushBuffer();
        } catch (IOException e) {

        }
    }

    /**
     * 详情
     *
     * @param id
     * @return
     */
    @Override
    public HazardAccount getInfo(String id) {
        HazardAccount hazardAccount = baseMapper.selectById(id);
        if (hazardAccount != null) {
            ResultBody<List<String>> resultBody = fileApi.getFileIdsByBusinessId(id);
            if (resultBody != null && CollectionUtils.isNotEmpty(resultBody.getData())) {
                hazardAccount.setFileIds(resultBody.getData());
            }
        }

        return hazardAccount;
    }

    @Override
    public void delete(String id) {
        lambdaUpdate().eq(HazardAccount::getHazardId, id).set(HazardAccount::getIsDelete, Constants.ONE_STR).update();
    }


}
